#! user/bin/python
# -*- coding: utf-8 -*-

"""
Created on 2021/6/28 10:14

@File: self_guimaker.py
@Author: LT
@Description: Use of this module
"""
import sys
from tkinter import *
from tkinter.messagebox import *


class GuiMaker(Frame):
    menuBar = []
    toolBar = []
    helpButton = True

    def __init__(self, parent=None):
        Frame.__init__(self, parent)
        self.pack(expand=YES, fill=BOTH)

        self.start()                # start方法必须放在后面所有方法的前面位置，否则会出错
        self.makeMenuBar()
        self.makeToolBar()
        self.makeWidgets()

    def makeMenuBar(self):
        """
        在顶部创建菜单栏
        """
        menubuttoncontainer = Frame(self, relief=RAISED, bd=2)
        menubuttoncontainer.pack(side=TOP, fill=X)

        for name, key, items in self.menuBar:  # 待传入的已经预设好的3元组格式内容，转化成菜单组件
            # name是顶层菜单名；key就是underline值，0就是设置了快捷键；items就是各个下拉对象的建立
            mbutton = Menubutton(menubuttoncontainer, text=name, )
            mbutton.pack(side=LEFT)
            pulldown = Menu(mbutton)
            mbutton.config(menu=pulldown)
            self.addMenuItems(pulldown, items)

        if self.helpButton:
            Button(menubuttoncontainer,
                   text="Help",
                   cursor="cross",
                   relief=FLAT,
                   command=self.help
                   ).pack(side=RIGHT)

    def addMenuItems(self, menu, items):
        for item in items:
            if item == "separator":
                menu.add_separator()
            elif type(item) is list:
                for num in item:  # Configure a menu item at INDEX.即用索引对条目设置状态
                    menu.entryconfig(num, state=DISABLED)
            elif type(item[2]) is not list:
                menu.add_command(label=item[0],
                                 underline=item[1],
                                 command=item[2])
            else:  # 否则就是个元组嵌套，即当item[2]是个list的时候，就要开启递归了
                pullover = Menu(menu)
                self.addMenuItems(pullover, item[2])
                menu.add_cascade(label=item[0],
                                 underline=item[1],
                                 menu=pullover)

    def makeToolBar(self):
        if self.toolBar:
            toolBar = Frame(self, cursor="hand2", relief=SUNKEN, bd=2)
            toolBar.pack(side=BOTTOM, fill=X)
            for name, action, where in self.toolBar:
                Button(toolBar, text=name, command=action).pack(where)  # where是个字典，传入会被自动解包，无须担心

    def makeWidgets(self):
        name = Label(self,
                     width=40,
                     height=10,
                     relief=SUNKEN,
                     bg="white",
                     text=self.__class__.__name__,      # 将标签内容填写为创建此实例的类的名字
                     cursor="crosshair")
        name.pack(expand=YES, fill=BOTH, side=TOP)

    def help(self):
        """override me in subclass(在子类中重写它)"""
        showinfo('Help', 'Sorry, no help for ' + self.__class__.__name__)

    def start(self):
        """override me in subclass: set menu/toolbar with self"""
        pass


###############################################################################
# 定制化一个不用容器Frame，而是直接与主窗口关联的菜单栏
###############################################################################
GuiMakerFrameMenu = GuiMaker                # 用这个就可以直接在名字上区分是作嵌入式的菜单栏


class GuiMakerWindowMenu(GuiMaker):         # 还是做与顶层窗口相关联的菜单栏
    def makeMenuBar(self):
        """
        重写它的创建菜单栏函数
        """
        menuBar = Menu(self.master)
        self.master.config(menu=menuBar)

        for name, key, items in self.menuBar:
            pulldown = Menu(menuBar)
            self.addMenuItems(pulldown, items)
            menuBar.add_cascade(label=name,
                                underline=key,
                                menu=pulldown)

        if self.helpButton:
            if sys.platform[:3] == "win":
                menuBar.add_command(label="Help", command=self.help)
            else:
                pulldown = Menu(menuBar)        # 比如linux系统就需要真正的下拉对象
                pulldown.add_command(label="About", command=self.help)
                menuBar.add_cascade(label="Help", menu=pulldown)


if __name__ == '__main__':
    from self_guimixin import GuiMixin  # mix in a help method

    menuBar = [
        ('File', 0,
         [('Open', 0, lambda: 0),  # lambda:0 is a no-op
          ('Quit', 0, sys.exit),
          'separator',
          [0, 1, 2],  # 对此下拉菜单对象的012条目设置禁用
          ("LaLaLa", 0, [
              ('LaLaLaOpen', 0, lambda: 0),  # lambda:0 is a no-op
              ('LaLaLaQuit', 0, sys.exit),
              'separator',
              [0, 1, 2],  # 对此下拉菜单对象的012条目设置禁用
          ])
          ],),  # use sys, no self here
        ('Edit', 0,
         [('Cut', 0, lambda: 0),
          ('Paste', 0, lambda: 0)])]
    toolBar = [('Quit', sys.exit, {'side': LEFT})]


    class TestAppFrameMenu(GuiMixin, GuiMakerFrameMenu):
        def start(self):
            self.menuBar = menuBar
            self.toolBar = toolBar


    class TestAppWindowMenu(GuiMixin, GuiMakerWindowMenu):
        def start(self):
            self.menuBar = menuBar
            self.toolBar = toolBar


    class TestAppWindowMenuBasic(GuiMakerWindowMenu):       # 不使用混合类的情况
        def start(self):
            self.menuBar = menuBar
            self.toolBar = toolBar  # guimaker help, not guimixin


    root = Tk()
    TestAppFrameMenu(Toplevel())
    TestAppWindowMenu(Toplevel())
    TestAppWindowMenuBasic(root)
    root.mainloop()
